{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 21点的策略研究 ##"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from random import randint\n",
    "import numpy as np\n",
    "from tqdm import trange\n",
    "import pandas as pd\n",
    "steps = 100000"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>定义一个庄家的对象</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Dealer:\n",
    "    flag_ace = False\n",
    "    firstcard = 0\n",
    "    cards = []\n",
    "\n",
    "    def __init__(self, card):\n",
    "        if card>10:\n",
    "            card=10\n",
    "        self.firstcard = card\n",
    "\n",
    "    def getcard(self):\n",
    "        card = randint(1,13)\n",
    "        if card>10:\n",
    "            card=10\n",
    "        if card==1:\n",
    "            self.flag_ace = True\n",
    "        self.cards.append(card)\n",
    "\n",
    "    def calculatescore(self):\n",
    "        score = np.sum(np.array(self.cards))\n",
    "        if self.flag_ace:\n",
    "            if score<=11:\n",
    "                score += 10    #This means one ace can be treat as 11 not 1\n",
    "        return score\n",
    "\n",
    "    def play(self):\n",
    "        self.cards = [self.firstcard]\n",
    "        if self.firstcard==1:\n",
    "            self.flag_ace = True\n",
    "        else:\n",
    "            self.flag_ace = False\n",
    "        while True:\n",
    "            self.getcard()\n",
    "            score = self.calculatescore()\n",
    "            if self.flag_ace and score>17:\n",
    "                break\n",
    "            if self.flag_ace==False and score>16:\n",
    "                break\n",
    "        return score       "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>定义一个玩家对象</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Player:\n",
    "    cards = []\n",
    "    flag_ace = False\n",
    "    cardpool = []\n",
    "\n",
    "    def __init__(self, card1, card2):\n",
    "        self.cards = [card1, card2]\n",
    "        if card1==1 or card2==1:\n",
    "            self.flag_ace = True\n",
    "\n",
    "def hit(self, cardnum=-1):\n",
    "    if cardnum>=0:\n",
    "        card = self.cardpool[cardnum]\n",
    "    else:\n",
    "        card = randint(1,13)\n",
    "    if card>10:\n",
    "        card=10\n",
    "    if card==1:\n",
    "        self.flag_ace = True\n",
    "    self.cards.append(card)\n",
    "        \n",
    "\n",
    "    def calculatescore(self):\n",
    "        score = np.sum(np.array(self.cards))\n",
    "        if self.flag_ace:\n",
    "            if score<=11:\n",
    "                score += 10    #This means one ace can be treat as 11 not 1\n",
    "        return score\n",
    "    \n",
    "def play(self, dealercard, policy, simulate=False):\n",
    "    card1 = self.cards[0]\n",
    "    card2 = self.cards[1]\n",
    "    hitcount = 0\n",
    "    scale = 1.0\n",
    "    count = 0\n",
    "    while True:\n",
    "        if self.flag_ace and len(self.cards)==2:\n",
    "            if max(card1, card2)==10:\n",
    "                scale=1.5\n",
    "                score=21\n",
    "                break\n",
    "            else:\n",
    "                key = \"A,\"+str(np.sum(np.array(self.cards))-1)\n",
    "                action = policy[key][dealercard-1]\n",
    "        else:\n",
    "            score = self.calculatescore()\n",
    "            if score>=18:\n",
    "                break\n",
    "            else:\n",
    "                if self.flag_ace:\n",
    "                    cardsum = np.sum(np.array(self.cards))\n",
    "                    if cardsum<12:\n",
    "                        key = 'A,'+str(cardsum-1)\n",
    "                    else:\n",
    "                        key = str(score)\n",
    "                else:\n",
    "                    key = str(score)\n",
    "                action = policy[key][dealercard-1]\n",
    "        if (action=='D' or action=='D/S') and hitcount==0:\n",
    "            if simulate:\n",
    "                self.hit(0)\n",
    "            else:\n",
    "                self.hit()\n",
    "            score = self.calculatescore()\n",
    "            scale = 2.0\n",
    "            break\n",
    "        elif action=='S' or (action=='D/S' and hitcount>0):\n",
    "            score = self.calculatescore()\n",
    "            break\n",
    "        else:\n",
    "            if simulate:\n",
    "                self.hit(count)\n",
    "            else:\n",
    "                self.hit()\n",
    "            score = self.calculatescore()\n",
    "            if score>=18:\n",
    "                break\n",
    "            hitcount+=1\n",
    "            count += 1\n",
    "    return score, scale"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>要牌/加倍/停牌的策略研究</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "policy = {}\n",
    "policy['21'] = []\n",
    "policy['A,10'] = []\n",
    "for i in range(10):\n",
    "    policy['21'].append('S')\n",
    "    policy['A,10'].append('S')\n",
    "for card1 in range(10, 1, -1):\n",
    "    for card2 in range(10, 0, -1):\n",
    "        if card2==1:\n",
    "            key = 'A,'+str(card1)\n",
    "        else:\n",
    "            key = str(card1+card2)\n",
    "        if key in policy:\n",
    "            continue\n",
    "        else:\n",
    "            policy[key] = []\n",
    "        for dealercard in range(1, 11):\n",
    "            player1_money=10000\n",
    "            player2_money=10000\n",
    "            player3_money=10000\n",
    "            bet = 100\n",
    "            games = 100000\n",
    "            player1_policy = 'S'\n",
    "            player2_policy = 'D'  \n",
    "            player3_policy = 'H'\n",
    "\n",
    "            for i in range(games):\n",
    "                p = Player(card1, card2)\n",
    "                d = Dealer(dealercard)\n",
    "\n",
    "                score1 = p.calculatescore()   #For player1, stand\n",
    "                p.hit()\n",
    "                score2 = p.calculatescore() \n",
    "                score3 = p.calculatescore()   #For player2 double, player3 hit\n",
    "\n",
    "                while True:\n",
    "                    if score3>=20:\n",
    "                        break\n",
    "                    if p.flag_ace:\n",
    "                        cardsum = np.sum(np.array(p.cards))\n",
    "                        if cardsum-1<11:\n",
    "                            k = 'A,'+str(cardsum-1)\n",
    "                        else:\n",
    "                            k = str(score3)\n",
    "                    else:\n",
    "                        k = str(score3)\n",
    "                    if policy[k][dealercard-1]=='S' or policy[k][dealercard-1]=='D/S':\n",
    "                        break\n",
    "                    else:\n",
    "                        p.hit()\n",
    "                        score3 = p.calculatescore()\n",
    "\n",
    "                dealerscore = d.play()\n",
    "\n",
    "                if score2>21:\n",
    "                    if dealerscore>21:\n",
    "                        player1_money += bet\n",
    "                    else:\n",
    "                        if score1>dealerscore:\n",
    "                            player1_money += bet\n",
    "                        if score1<dealerscore:\n",
    "                            player1_money -= bet\n",
    "                    player2_money -= 2*bet\n",
    "                    player3_money -= bet\n",
    "                else:\n",
    "                    if score3>21:\n",
    "                        player3_money -= bet\n",
    "                        if dealerscore>21:\n",
    "                            player1_money += bet\n",
    "                            player2_money += 2*bet\n",
    "                        else:\n",
    "                            if score1>dealerscore:\n",
    "                                player1_money += bet\n",
    "                            if score1<dealerscore:\n",
    "                                player1_money -= bet\n",
    "                            if score2>dealerscore:\n",
    "                                player2_money += 2*bet\n",
    "                            if score2<dealerscore:\n",
    "                                player2_money -= 2*bet\n",
    "                            if dealerscore==21 and d.flag_ace==True and len(d.cards)==2:\n",
    "                                if score2==21:\n",
    "                                    player2_money -= 2*bet\n",
    "                    else:    #score1<=21, score2<=21, score3<=21\n",
    "                        if dealerscore>21:\n",
    "                            player1_money += bet\n",
    "                            player2_money += 2*bet\n",
    "                            player3_money += bet\n",
    "                        else:\n",
    "                            if score1>dealerscore:\n",
    "                                player1_money += bet\n",
    "                            if score1<dealerscore:\n",
    "                                player1_money -= bet\n",
    "                            if score2>dealerscore:\n",
    "                                player2_money += 2*bet\n",
    "                            if score2<dealerscore:\n",
    "                                player2_money -= 2*bet\n",
    "                            if score3>dealerscore:\n",
    "                                player3_money += bet\n",
    "                            if score3<dealerscore:\n",
    "                                player3_money -= bet\n",
    "                            if dealerscore==21 and d.flag_ace==True and len(d.cards)==2:\n",
    "                                if score2==21:\n",
    "                                    player2_money -= 2*bet\n",
    "                                if score3==21:\n",
    "                                    player3_money -= bet\n",
    "                del d,p\n",
    "\n",
    "            max_money = max(player1_money, player2_money, player3_money)\n",
    "            if max_money==player1_money:\n",
    "                policy[key].append('S')\n",
    "            if max_money==player2_money: \n",
    "                if player1_money>player3_money:\n",
    "                    policy[key].append('D/S')\n",
    "                else:\n",
    "                    policy[key].append('D')\n",
    "            if max_money==player3_money:\n",
    "                policy[key].append('H')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>保存得到的policy并展示</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "#调整policy中的Key的排序\n",
    "keys = sorted(policy.keys())\n",
    "sorted_keys = keys[12:18]\n",
    "sorted_keys.extend(keys[:12])\n",
    "sorted_keys.extend(keys[19:])\n",
    "sorted_keys.append(keys[18])\n",
    "with open('policy.csv', 'w') as f:\n",
    "    policy_result = 'Player;2;3;4;5;6;7;8;9;10;A\\n'\n",
    "    for key in sorted_keys:\n",
    "        policy_result += key+';'+';'.join(policy[key][1:])+';'+policy[key][0]+'\\n'\n",
    "    f.write(policy_result)\n",
    "df_policy = pd.read_csv('policy.csv', header=0, index_col=0, sep=';')\n",
    "df_policy.head(100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>分牌策略的研究及展示</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "split_result = {}\n",
    "for i in trange(2,10):\n",
    "    split_result[str(i)+\",\"+str(i)]=[]\n",
    "    for c in trange(1, 11):   #Dealer card 2-10, A\n",
    "        lose_counts = 0\n",
    "        win_counts = 0\n",
    "        draw_counts = 0\n",
    "        split_gain = 0\n",
    "        nonsplit_gain = 0\n",
    "        for j in range(steps):\n",
    "            for k in range(3):     #k-0,1, Split card, k-2, not split\n",
    "                d = Dealer(c)\n",
    "                while True:\n",
    "                    secondcard = randint(1,13)\n",
    "                    if secondcard>10:\n",
    "                        secondcard = 10\n",
    "                    if secondcard!=i:\n",
    "                        break\n",
    "                if k==2:\n",
    "                    secondcard = i\n",
    "                p = Player(i, secondcard)\n",
    "                hit_count = 0\n",
    "                player_lose = False\n",
    "                doublescaler = 1\n",
    "                while True:\n",
    "                    score = p.calculatescore()\n",
    "                    if score>18 and score<=21:\n",
    "                        break\n",
    "                    if score>21:\n",
    "                        player_lose = True\n",
    "                        break\n",
    "                    if p.flag_ace:\n",
    "                        cardsum = np.sum(np.array(p.cards))\n",
    "                        if cardsum-1<11:\n",
    "                            key = 'A,'+str(cardsum-1)\n",
    "                        else:\n",
    "                            key = str(score)\n",
    "                    else:\n",
    "                        key = str(score)\n",
    "                    action = policy[key][c-1]\n",
    "                    if hit_count==0: \n",
    "                        if action=='D' or action=='D/S':\n",
    "                            doublescaler = 2\n",
    "                    if (hit_count==0 and action=='D/S') or action=='D' or action=='H':\n",
    "                        p.hit()\n",
    "                        hit_count += 1\n",
    "                    else:\n",
    "                        score = p.calculatescore()\n",
    "                        if score>21:\n",
    "                            lose_counts += 1*doublescaler\n",
    "                            if k<2:\n",
    "                                split_gain -= 1*doublescaler\n",
    "                            else:\n",
    "                                nonsplit_gain -= 1*doublescaler\n",
    "                            player_lose = True\n",
    "                            break\n",
    "                        else:\n",
    "                            player_lose = False\n",
    "                            break\n",
    "                if player_lose==False:\n",
    "                    dealerscore = d.play()\n",
    "                    if dealerscore>21:\n",
    "                        win_counts += 1*doublescaler\n",
    "                        if k<2:\n",
    "                            split_gain += 1*doublescaler\n",
    "                        else:\n",
    "                            nonsplit_gain += 1*doublescaler\n",
    "                    else:\n",
    "                        if score<dealerscore:\n",
    "                            lose_counts += 1*doublescaler\n",
    "                            if k<2:\n",
    "                                split_gain -= 1*doublescaler\n",
    "                            else:\n",
    "                                nonsplit_gain -= 1*doublescaler\n",
    "                        elif score>dealerscore:\n",
    "                            win_counts += 1*doublescaler\n",
    "                            if k<2:\n",
    "                                split_gain += 1*doublescaler\n",
    "                            else:\n",
    "                                nonsplit_gain += 1*doublescaler\n",
    "                        else:\n",
    "                            draw_counts += 1\n",
    "                else:\n",
    "                    if k<2:\n",
    "                        split_gain -= 1*doublescaler\n",
    "                    else:\n",
    "                        nonsplit_gain -= 1*doublescaler\n",
    "                del d, p\n",
    "        split_result[str(i)+\",\"+str(i)].append([split_gain,nonsplit_gain]) \n",
    "        \n",
    "split_policy = {}\n",
    "for key in split_result:\n",
    "    split_policy[key] = []\n",
    "    for i in range(10):\n",
    "        if split_result[key][i][0]<split_result[key][i][1]:\n",
    "            policykey = str(int(key.split(',')[0])*2)\n",
    "            split_policy[key].append(policy[policykey][i])\n",
    "        else:\n",
    "            split_policy[key].append('P')\n",
    "\n",
    "split_policy_result = 'Player;2;3;4;5;6;7;8;9;10;A\\n'\n",
    "for key in split_policy:\n",
    "    split_policy_result += key+';'+';'.join(split_policy[key][1:])+';'+split_policy[key][0]+'\\n'\n",
    "with open('split_policy.csv', 'w') as f:\n",
    "    f.write(split_policy_result)\n",
    "df_split = pd.read_csv('split_policy.csv', header=0, index_col=0, sep=';')\n",
    "df_split.head(100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>合并全部策略</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('policy.csv', 'r') as f:\n",
    "    lines = f.readlines()\n",
    "with open('split_policy.csv', 'r') as f:\n",
    "    lines.extend(f.readlines()[1:])\n",
    "complete_policy = {}\n",
    "for l in lines[1:]:\n",
    "    a = l.strip().split(';')\n",
    "    complete_policy[a[0]] = [a[-1]]\n",
    "    complete_policy[a[0]].extend(a[1:])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>评估策略效果</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 207,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 1/1 [00:00<00:00, 500.27it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Game 0:\n",
      "Player:10,5,10\n",
      "Dealer:10,4,9\n",
      "TotalMoney:900\n",
      "Game 1:\n",
      "Player:4,8\n",
      "Dealer:4,10,10\n",
      "TotalMoney:1000.0\n",
      "Game 2:\n",
      "Player:1,10\n",
      "Dealer:2,4,9,8\n",
      "TotalMoney:1150.0\n",
      "Game 3:\n",
      "Player:10,10\n",
      "Dealer:4,9,6\n",
      "TotalMoney:1250.0\n",
      "Game 4:\n",
      "Player:10,8\n",
      "Dealer:5,10,10\n",
      "TotalMoney:1350.0\n",
      "Game 5:\n",
      "Player:3,10\n",
      "Dealer:2,1,8\n",
      "TotalMoney:1250.0\n",
      "Game 6:\n",
      "Player:2,3,2,10\n",
      "Dealer:7,9,4\n",
      "TotalMoney:1150.0\n",
      "Game 7:\n",
      "Player:10,1\n",
      "Dealer:8,10\n",
      "TotalMoney:1300.0\n",
      "Game 8:\n",
      "Player:9,5\n",
      "Dealer:3,6,6,5\n",
      "TotalMoney:1200.0\n",
      "Game 9:\n",
      "Player:3,10\n",
      "Dealer:4,10,10\n",
      "TotalMoney:1300.0\n",
      "[1300.0]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "bet = 100\n",
    "games = 10\n",
    "loops = 1\n",
    "debug = True\n",
    "money = []\n",
    "for j in trange(loops):\n",
    "    totalmoney = 1000\n",
    "    for i in range(games):\n",
    "        if debug:\n",
    "            print('Game {}:'.format(i))\n",
    "        dealercard = randint(1,13)\n",
    "        if dealercard>10:\n",
    "            dealercard = 10\n",
    "        d = Dealer(dealercard)\n",
    "\n",
    "        card1 = randint(1,13)\n",
    "        scores = []\n",
    "        if card1>10:\n",
    "            card1 = 10\n",
    "        card2 = randint(1,13)\n",
    "        if card2>10:\n",
    "            card2 = 10\n",
    "        action = ''\n",
    "\n",
    "        if card1==card2 and card1!=10:\n",
    "            if card1==1:\n",
    "                action = 'P'\n",
    "            else:\n",
    "                key = str(card1)+','+str(card2)\n",
    "                action = complete_policy[key][dealercard-1]\n",
    "        if action=='P':\n",
    "            split_times = 2\n",
    "            while split_times>0:\n",
    "                card = randint(1,13)\n",
    "                card_count += 1\n",
    "                if card>10:\n",
    "                    card=10\n",
    "                if card!=card1:\n",
    "                    p_temp = Player(card1, card)\n",
    "                    score, scale = p_temp.play(dealercard, complete_policy, False)\n",
    "                    playercards = [str(a) for a in p_temp.cards]\n",
    "                    if debug:\n",
    "                        print('Player:'+','.join(playercards))\n",
    "                    del p_temp\n",
    "                    scores.append((score, scale))\n",
    "                    split_times -= 1\n",
    "                else:\n",
    "                    split_times += 1\n",
    "        else:\n",
    "            p = Player(card1, card2)\n",
    "            score, scale = p.play(dealercard, complete_policy, False)\n",
    "            scores.append((score, scale))\n",
    "            playercards = [str(a) for a in p.cards]\n",
    "            if debug:\n",
    "                print('Player:'+','.join(playercards))\n",
    "            del p\n",
    "\n",
    "        dealerscore = d.play()\n",
    "        dealercards = [str(a) for a in d.cards]\n",
    "        if debug:\n",
    "            print('Dealer:'+','.join(dealercards))\n",
    "\n",
    "        for item in scores:\n",
    "            score, scale = item\n",
    "            if score>21:\n",
    "                totalmoney -= bet\n",
    "            else:\n",
    "                if score==21 and scale==1.5:\n",
    "                    if dealerscore==21 and len(d.cards)==2:\n",
    "                        continue\n",
    "                    else:\n",
    "                        totalmoney += bet*1.5\n",
    "                else:\n",
    "                    if dealerscore>21:\n",
    "                        totalmoney += bet*scale\n",
    "                    elif dealerscore==21 and len(d.cards)==2:\n",
    "                        if score==21 and scale==1.5:\n",
    "                            continue\n",
    "                        else:\n",
    "                            totalmoney -= bet*scale\n",
    "                    else:\n",
    "                        if score>dealerscore:\n",
    "                            totalmoney += bet*scale\n",
    "                        elif score<dealerscore:\n",
    "                            totalmoney -= bet*scale\n",
    "                        else:\n",
    "                            continue\n",
    "        del d\n",
    "        if debug:\n",
    "            print(\"TotalMoney:{}\".format(totalmoney))\n",
    "    money.append(totalmoney)\n",
    "print(money)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>和标准策略做对比，看哪个策略更好</b>\n",
    "<p>\n",
    "<b>加载标准策略并展示</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 213,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "      <th>4</th>\n",
       "      <th>5</th>\n",
       "      <th>6</th>\n",
       "      <th>7</th>\n",
       "      <th>8</th>\n",
       "      <th>9</th>\n",
       "      <th>10</th>\n",
       "      <th>A</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Player</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>H</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A,2</th>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A,3</th>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A,4</th>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A,5</th>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A,6</th>\n",
       "      <td>H</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A,7</th>\n",
       "      <td>S</td>\n",
       "      <td>D/S</td>\n",
       "      <td>D/S</td>\n",
       "      <td>D/S</td>\n",
       "      <td>D/S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A,8</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A,9</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A,10</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2,2</th>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3,3</th>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4,4</th>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5,5</th>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>D</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6,6</th>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7,7</th>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "      <td>H</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8,8</th>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9,9</th>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>S</td>\n",
       "      <td>P</td>\n",
       "      <td>P</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10,10</th>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "      <td>S</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        2    3    4    5    6  7  8  9 10  A\n",
       "Player                                      \n",
       "5       H    H    H    H    H  H  H  H  H  H\n",
       "6       H    H    H    H    H  H  H  H  H  H\n",
       "7       H    H    H    H    H  H  H  H  H  H\n",
       "8       H    H    H    H    H  H  H  H  H  H\n",
       "9       H    D    D    D    D  H  H  H  H  H\n",
       "10      D    D    D    D    D  D  D  D  H  H\n",
       "11      D    D    D    D    D  D  D  D  D  H\n",
       "12      H    H    S    S    S  H  H  H  H  H\n",
       "13      S    S    S    S    S  H  H  H  H  H\n",
       "14      S    S    S    S    S  H  H  H  H  H\n",
       "15      S    S    S    S    S  H  H  H  H  H\n",
       "16      S    S    S    S    S  H  H  H  H  H\n",
       "17      S    S    S    S    S  S  S  S  S  S\n",
       "18      S    S    S    S    S  S  S  S  S  S\n",
       "19      S    S    S    S    S  S  S  S  S  S\n",
       "A,2     H    H    H    D    D  H  H  H  H  H\n",
       "A,3     H    H    H    D    D  H  H  H  H  H\n",
       "A,4     H    H    D    D    D  H  H  H  H  H\n",
       "A,5     H    H    D    D    D  H  H  H  H  H\n",
       "A,6     H    D    D    D    D  H  H  H  H  H\n",
       "A,7     S  D/S  D/S  D/S  D/S  S  S  H  H  H\n",
       "A,8     S    S    S    S    S  S  S  S  S  S\n",
       "A,9     S    S    S    S    S  S  S  S  S  S\n",
       "A,10    S    S    S    S    S  S  S  S  S  S\n",
       "2,2     P    P    P    P    P  P  H  H  H  H\n",
       "3,3     P    P    P    P    P  P  H  H  H  H\n",
       "4,4     H    H    H    P    P  H  H  H  H  H\n",
       "5,5     D    D    D    D    D  D  D  D  H  H\n",
       "6,6     P    P    P    P    P  H  H  H  H  H\n",
       "7,7     P    P    P    P    P  P  H  H  H  H\n",
       "8,8     P    P    P    P    P  P  P  P  P  P\n",
       "9,9     P    P    P    P    P  S  P  P  S  S\n",
       "10,10   S    S    S    S    S  S  S  S  S  S"
      ]
     },
     "execution_count": 213,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "standard_policy = {}\n",
    "with open('standard_policy.csv', 'r') as f:\n",
    "    lines = f.readlines()\n",
    "    for l in lines[1:]:\n",
    "        a = l.strip().split(';')\n",
    "        standard_policy[a[0]] = [a[-1]]\n",
    "        standard_policy[a[0]].extend(a[1:-1])\n",
    "standard_policy['4'] = standard_policy['5']\n",
    "df_std = pd.read_csv('standard_policy.csv', header=0, index_col=0, sep=';')\n",
    "df_std.head(100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>比较两种策略的优劣</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 221,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 1000/1000 [00:45<00:00, 21.79it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "450\n",
      "402\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "bet = 100\n",
    "games = 100\n",
    "loops = 1000\n",
    "debug = False\n",
    "money = []\n",
    "mypolicywins = 0\n",
    "stdpolicywins = 0\n",
    "policys = [standard_policy, complete_policy]\n",
    "for j in trange(loops):\n",
    "    totalmoney = [100000,100000]\n",
    "    for i in range(games):\n",
    "        if debug:\n",
    "            print('Game {}:'.format(i))\n",
    "        dealercard = randint(1,13)\n",
    "        if dealercard>10:\n",
    "            dealercard = 10\n",
    "        d = Dealer(dealercard)\n",
    "\n",
    "        card1 = randint(1,13)\n",
    "        scores = [[],[]]\n",
    "        if card1>10:\n",
    "            card1 = 10\n",
    "        card2 = randint(1,13)\n",
    "        if card2>10:\n",
    "            card2 = 10\n",
    "        cardpool = []\n",
    "        splitpool = []\n",
    "        for cardpoolnum in range(200):\n",
    "            cardpool.append(randint(1,13))\n",
    "        for splitpoolnum in range(10):\n",
    "            splitpool.append([])\n",
    "            for a in range(20):\n",
    "                splitpool[-1].append(randint(1,13))\n",
    "        action = ''\n",
    "        for policyid in range(2):\n",
    "            if debug:\n",
    "                if policyid==0:\n",
    "                    print(\"Standardpolicy\")\n",
    "                else:\n",
    "                    print(\"completepolicy\")\n",
    "            if card1==card2 and card1!=10:\n",
    "                if card1==1:\n",
    "                    action = 'P'\n",
    "                else:\n",
    "                    key = str(card1)+','+str(card2)\n",
    "                    action = policys[policyid][key][dealercard-1]\n",
    "            if action=='P':\n",
    "                split_times = 2\n",
    "                split_count = 0\n",
    "                card_count = 0\n",
    "                while split_times>0:\n",
    "                    card = cardpool[card_count]\n",
    "                    card_count += 1\n",
    "                    if card>10:\n",
    "                        card=10\n",
    "                    if card!=card1:\n",
    "                        p_temp = Player(card1, card)\n",
    "                        p_temp.cardpool = splitpool[split_count]\n",
    "                        split_count += 1\n",
    "                        score, scale = p_temp.play(dealercard, policys[policyid], True)\n",
    "                        playercards = [str(a) for a in p_temp.cards]\n",
    "                        if debug:\n",
    "                            print('Player:'+','.join(playercards))\n",
    "                        del p_temp\n",
    "                        scores[policyid].append((score, scale))\n",
    "                        split_times -= 1\n",
    "                    else:\n",
    "                        split_times += 1\n",
    "            else:\n",
    "                p = Player(card1, card2)\n",
    "                p.cardpool = cardpool\n",
    "                score, scale = p.play(dealercard, policys[policyid], True)\n",
    "                scores[policyid].append((score, scale))\n",
    "                playercards = [str(a) for a in p.cards]\n",
    "                if debug:\n",
    "                    print('Player:'+','.join(playercards))\n",
    "                del p\n",
    "\n",
    "        dealerscore = d.play()\n",
    "        dealercards = [str(a) for a in d.cards]\n",
    "        if debug:\n",
    "            print('Dealer:'+','.join(dealercards))\n",
    "\n",
    "        for policyid in range(2):\n",
    "            for item in scores[policyid]:\n",
    "                score, scale = item\n",
    "                if score>21:\n",
    "                    totalmoney[policyid] -= bet\n",
    "                else:\n",
    "                    if score==21 and scale==1.5:\n",
    "                        if dealerscore==21 and len(d.cards)==2:\n",
    "                            continue\n",
    "                        else:\n",
    "                            totalmoney[policyid] += bet*1.5\n",
    "                    else:\n",
    "                        if dealerscore>21:\n",
    "                            totalmoney[policyid] += bet*scale\n",
    "                        elif dealerscore==21 and len(d.cards)==2:\n",
    "                            if score==21 and scale==1.5:\n",
    "                                continue\n",
    "                            else:\n",
    "                                totalmoney[policyid] -= bet*scale\n",
    "                        else:\n",
    "                            if score>dealerscore:\n",
    "                                totalmoney[policyid] += bet*scale\n",
    "                            elif score<dealerscore:\n",
    "                                totalmoney[policyid] -= bet*scale\n",
    "                            else:\n",
    "                                continue\n",
    "        del d\n",
    "        if debug:\n",
    "            print(\"TotalMoney:{}\".format(totalmoney))\n",
    "    if totalmoney[0]<totalmoney[1]:\n",
    "        #print('My policy win')\n",
    "        mypolicywins += 1\n",
    "    if totalmoney[0]>totalmoney[1]:\n",
    "        stdpolicywins += 1\n",
    "        #print('Standard policy win')\n",
    "    \n",
    "print(mypolicywins)\n",
    "print(stdpolicywins)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 219,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[100550.0, 100850.0]"
      ]
     },
     "execution_count": 219,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "totalmoney"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
